﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using DiscoveryLogic.DataServices.DataSources;
using DiscoveryLogic.UI.Layouts.Converters;
using DiscoveryLogic.UI.Layouts.Models;

namespace DiscoveryLogic.UI.Layouts.Controls
{
    public partial class Enrollment529SavingsVis : UserControl
    {
        #region Private Variables

            double marketGrowth;
            double savingsTarget = 0;
            double initialInvestment = 0;
            double monthlyContributionsNoGrowth = 0;
            double monthlyContributionsWithGrowth = 0;

            double barChartMax = 200000;
            double barChartMin = 0;
            private double barChartValue;
            private double barChartGoalValue;

            Child child;

            // Chart Variables
            private double axisTop;
            private double axisLength;

        #endregion

        #region Constructors

            public Enrollment529SavingsVis(Child c, double marketGrowth)
            {
                // Initialize Variables
                InitializeComponent();

                this.marketGrowth = marketGrowth;
                child = c;

                axisLength = BarChartAxis.Height;
                axisTop = (double)BarChartAxis.GetValue(Canvas.TopProperty);

                // Initialize Sliders
                SavingsTargetSlider.Minimum = barChartMin;
                SavingsTargetSlider.Maximum = barChartMax;

                InitialInvestmentSlider.Minimum = barChartMin;
                InitialInvestmentSlider.Maximum = 100000;

                // Initialize Bars on Bar Chart
                // Set dashed stroke for hollow cylinder 1
                BarHollowCylinder.Stroke = new SolidColorBrush(Colors.LightGray);
                BarHollowCylinder.StrokeThickness = 3;
                DoubleCollection dashes = new DoubleCollection();
                dashes.Add(3);
                dashes.Add(3);
                BarHollowCylinder.StrokeDashArray = dashes;
                BarHollowCylinder.StrokeDashCap = PenLineCap.Square;

                // Set dashed stroke for hollow cylinder 2
                BarHollowCylinder2.Stroke = new SolidColorBrush(Colors.LightGray);
                BarHollowCylinder2.StrokeThickness = 3;               
                DoubleCollection dashes2 = new DoubleCollection();
                dashes2.Add(3);
                dashes2.Add(3);
                BarHollowCylinder2.StrokeDashArray = dashes2;
                BarHollowCylinder2.StrokeDashCap = PenLineCap.Square;

                BarChartAmountMaxLabel.Text = barChartMax.ToCurrency();

                // Find savings target

                SavingsTarget = child.CostOfCollege;
                SavingsTargetSlider.Value = SavingsTarget;

                InitialInvestment = child.InitialInvestment;
                InitialInvestmentSlider.Value = InitialInvestment;

                // Recalculate and redraw bars based on sldier settings
                RedrawBarCharts();
            }

        #endregion

        #region Event Handlers

            private void SavingsTargetSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
            {
                SavingsTarget = SavingsTargetSlider.Value;
            }

            private void InitialInvestmentSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
            {
                InitialInvestment = InitialInvestmentSlider.Value;
            }

            private void BarChartAnim_Completed(object sender, EventArgs e)
            {
                if ((double)BarCylinder.GetValue(Canvas.TopProperty)
                    - (double)BarHollowCylinder.GetValue(Canvas.TopProperty) < 15)
                {
                    BarSavingsLabel.Opacity = 0;
                }
                else
                {
                    BarSavingsLabel.Opacity = 1;
                }

            }

            private void BarChart2Anim_Completed(object sender, EventArgs e)
            {
                if ((double)BarCylinder2.GetValue(Canvas.TopProperty)
                    - (double)BarHollowCylinder2.GetValue(Canvas.TopProperty) < 15)
                {
                    Bar2SavingsLabel.Opacity = 0;
                }
                else
                {
                    Bar2SavingsLabel.Opacity = 1;
                }
            }

        #endregion

        #region Get/Set Properties
            
            public double SavingsTarget
            {
                get { return savingsTarget; }
                set 
                { 
                    savingsTarget = value;
                    SavingsTargetLabel.Text = Math.Round(savingsTarget).ToCurrency();
                    RedrawBarCharts();
                }
            }

            public double InitialInvestment
            {
                get { return initialInvestment; }
                set 
                {
                    initialInvestment = value;
                    InitialInvestmentLabel.Text = Math.Round(initialInvestment).ToCurrency();
                    RedrawBarCharts();
                }
            }

            public double MonthlyContributionsNoGrowth
            {
                get { return monthlyContributionsNoGrowth; }
                set { monthlyContributionsNoGrowth = value; }
            }

            public double MonthlyContributionsWithGrowth
            {
                get { return monthlyContributionsWithGrowth; }
                set { monthlyContributionsWithGrowth = value; }
            }

        #endregion

        #region Helper Methods

            private void RedrawBarCharts()
            {
                // Calculate how much the contribution amount grows to by retirement                
                double percent;

                // 19 is when you start college and 3.5 years to finish
                double monthsUntilEndOfCollege = (19 - child.Age + 3.5) * 12;
                MonthlyContributionsNoGrowth = (SavingsTarget - InitialInvestment) / monthsUntilEndOfCollege;
                if (MonthlyContributionsNoGrowth < 0)
                {
                    MonthlyContributionsNoGrowth = 0;
                }

                // Find value of bar
                barChartValue = SavingsTarget;


                barChartGoalValue = SavingsTarget;
                

                if (barChartGoalValue <= 0)
                {
                    GoalIndicatorCanvas.Opacity = 0;
                }
                else
                {
                    GoalIndicatorCanvas.Opacity = 1;
                }

                double length = barChartMax - barChartMin;

                // Set bar position and height for savings                                          
                percent = (barChartValue - barChartMin) / length;
                double hollowBarTop = axisTop + axisLength - (axisLength * percent);
                double hollowBarHeight = axisTop + axisLength - hollowBarTop;

                // Set bar position and height for initial investment
                percent = (InitialInvestment - barChartMin) / length;
                double barTop = axisTop + axisLength - (axisLength * percent);
                double barHeight = axisTop + axisLength - barTop;

                try
                {
                    HollowBarChartHeightAnimKeyFrame.Value = hollowBarHeight;
                    HollowBarChartTopAnimKeyFrame.Value = hollowBarTop;
                    BarChartHeightAnimKeyFrame.Value = barHeight;
                    BarChartTopAnimKeyFrame.Value = barTop;
                    BarChartAnim.Begin();
                }
                catch  { }

                // Calculate initial investment with market growth
                double initialInvestmentWithGrowth = InitialInvestment;
                for (int i = 0; i < monthsUntilEndOfCollege; i++)
                {
                    initialInvestmentWithGrowth += initialInvestmentWithGrowth * (marketGrowth/12);
                }

                // Find monthly contributions with growth
                MonthlyContributionsWithGrowth = (SavingsTarget - initialInvestmentWithGrowth) / monthsUntilEndOfCollege;
                if (MonthlyContributionsWithGrowth < 0)
                {
                    MonthlyContributionsWithGrowth = 0;
                }
                child.MonthlyContribution = MonthlyContributionsWithGrowth;

                // Set bar2 position and height                    
                percent = (barChartValue - barChartMin) / length;
                double hollowBar2Top = axisTop + axisLength - (axisLength * percent);
                double hollowBar2Height = axisTop + axisLength - hollowBar2Top;
          
                percent = (initialInvestmentWithGrowth - barChartMin) / length;
                double bar2Top = axisTop + axisLength - (axisLength * percent);
                double bar2Height = axisTop + axisLength - bar2Top;
                
                try
                {
                    HollowBarChart2HeightAnimKeyFrame.Value = hollowBar2Height;
                    HollowBarChart2TopAnimKeyFrame.Value = hollowBar2Top;
                    BarChart2HeightAnimKeyFrame.Value = bar2Height;
                    BarChart2TopAnimKeyFrame.Value = bar2Top;
                    BarChart2Anim.Begin();
                }
                catch  { }

                // Set goal position
                percent = (barChartGoalValue - barChartMin) / length;
                double goalTop = axisTop + axisLength - (axisLength * percent);

                try
                {
                    BarChartGoalTopAnimKeyFrame.Value = goalTop;
                    BarChartGoalAnim.Begin();
                }
                catch  { }

                // Set labels
                BarValueLabel.Text = Convert.ToInt32(InitialInvestment).ToCurrency();
                Bar2ValueLabel.Text = Convert.ToInt32(initialInvestmentWithGrowth).ToCurrency();
                GoalValueLabel.Text = Convert.ToInt32(barChartGoalValue).ToCurrency();

                double savingsLabelPosition = hollowBarTop + ((barTop - hollowBarTop) / 2) - 10;

                // Position savings label for bar 1
                BarSavingsLabel.SetValue(Canvas.TopProperty, savingsLabelPosition);

                savingsLabelPosition = hollowBar2Top + ((bar2Top - hollowBar2Top) / 2) - 10;

                // Hide savings labels
                BarSavingsLabel.Opacity = 0;               
                Bar2SavingsLabel.Opacity = 0;
                
                // Position savings label for bar 2
                Bar2SavingsLabel.SetValue(Canvas.TopProperty, savingsLabelPosition);

                // Notify that monthly contributions have changed
                if (monthlyContributionChanged != null)
                {
                    monthlyContributionChanged(this, new EventArgs());
                }
            }

        #endregion

        #region Public Methods

            public void FocusOn()
            {
                SavingsTargetSlider.Value = SavingsTargetSlider.Value + 1;
                SavingsTargetSlider.Value = SavingsTargetSlider.Value - 1;
                SavingsTargetFrame.Width = SavingsTargetFrame.Width + 10;
                SavingsTargetFrame.Width = SavingsTargetFrame.Width - 10;
                InitialInvestmentFrame.Width = InitialInvestmentFrame.Width + 10;
                InitialInvestmentFrame.Width = InitialInvestmentFrame.Width - 10;
                RedrawBarCharts();
            }            

        #endregion

        #region Events

            public event EventHandler monthlyContributionChanged;

        #endregion


    }
}
